#include "SchmidtCAM.h"

time_t arm_sys_time = 0;
struct timeval start;
struct timeval end;

char timestamp0[26]; // 'op' + 23+'\n' = 26
char timestamp1[26]; // 'cl' + 23+'\n' = 26
char timestamp[51];

////////////////////////////////////////////////////////////////////////////////////
// 备份CCD驱动时序参数
// backup vtrans parameters
int vtrans_num_bak; //      = mcfg->config_ccd_drive->vtrans_num;
int imgCLK1_cnt_min_bak;    // = mcfg->config_ccd_drive->imgCLK1_cnt_min;
int imgCLK1_cnt_max_bak;    // = mcfg->config_ccd_drive->imgCLK1_cnt_max;
int imgCLK2_cnt_min_bak;    // = mcfg->config_ccd_drive->imgCLK2_cnt_min;
int imgCLK2_cnt_max_bak;    // = mcfg->config_ccd_drive->imgCLK2_cnt_max;
int imgCLK3_cnt_min_bak;    // = mcfg->config_ccd_drive->imgCLK3_cnt_min;
int imgCLK3_cnt_max_bak;    // = mcfg->config_ccd_drive->imgCLK3_cnt_max;
int imgCLK4_cnt_min_bak;    // = mcfg->config_ccd_drive->imgCLK4_cnt_min;
int imgCLK4_cnt_max_bak;    // = mcfg->config_ccd_drive->imgCLK4_cnt_max;
int imgCLKx_cnt_MAX_bak;    // = mcfg->config_ccd_drive->imgCLKx_cnt_MAX;
int vtrans_state_cnt_max_bak;   // = mcfg->config_ccd_drive->vtrans_state_cnt_max;

// backup htrans parameters
int htrans_num_bak; // = mcfg->config_ccd_drive->htrans_num;
///////////////////////////////////////////////////////////////////////////////////

SchmidtCAM_Config *scfg;

int main( int argc, char *argv[] ){

	//=================================================
    //  导入所有配置参数
    //=================================================
    char config_dir[1024];      // 保存参数配置文件所在的目录(相对路径)

    FILE *fp_wkdir = fopen(".WKDIR", "r");
    fscanf(fp_wkdir, "%s", config_dir);
    fclose(fp_wkdir);

    SchmidtCAM_Config SCAM_Config;
    init_SchmidtCAM_Config( &SCAM_Config, config_dir );

    // backup vtrans parameters
    vtrans_num_bak          = SCAM_Config.config_ccd_drive->vtrans_num;
    imgCLK1_cnt_min_bak     = SCAM_Config.config_ccd_drive->imgCLK1_cnt_min;
    imgCLK1_cnt_max_bak     = SCAM_Config.config_ccd_drive->imgCLK1_cnt_max;
    imgCLK2_cnt_min_bak     = SCAM_Config.config_ccd_drive->imgCLK2_cnt_min;
    imgCLK2_cnt_max_bak     = SCAM_Config.config_ccd_drive->imgCLK2_cnt_max;
    imgCLK3_cnt_min_bak     = SCAM_Config.config_ccd_drive->imgCLK3_cnt_min;
    imgCLK3_cnt_max_bak     = SCAM_Config.config_ccd_drive->imgCLK3_cnt_max;
    imgCLK4_cnt_min_bak     = SCAM_Config.config_ccd_drive->imgCLK4_cnt_min;
    imgCLK4_cnt_max_bak     = SCAM_Config.config_ccd_drive->imgCLK4_cnt_max;
    imgCLKx_cnt_MAX_bak     = SCAM_Config.config_ccd_drive->imgCLKx_cnt_MAX;
    vtrans_state_cnt_max_bak= SCAM_Config.config_ccd_drive->vtrans_state_cnt_max;

    // printf("debug: vtrans_state_cnt_max_bak = %d\n", vtrans_state_cnt_max_bak);
    // exit(0);
    
    // backup htrans parameters
    htrans_num_bak          = SCAM_Config.config_ccd_drive->htrans_num;


    //=========================================================================
    // GPIO 
    // uint32_t *gpio_flt_ctrl;        // ADDR_Float_Point_CTRL
    // uint32_t *gpio_flt_data;        // ADDR_Float_Point_DATA
    // uint32_t *gpio_in;              // ADDR_GPIO_IN
    // uint32_t *gpio_pl_ps;           // ADDR_PL_PS_DDR_CNT
    // uint32_t *gpio_out;             // ADDR_GPIO_OUT
    // uint32_t *gpio_out2;            // ADDR_GPIO_OUT
    // uint32_t *gpio_spi_ps_ctrl;     // ADDR_GPIO_SPI_PS_CTRL
    // uint32_t *gpio_spi_ps_data;     // ADDR_GPIO_SPI_PS_DATA

    int fd_gpio = open("/dev/mem", O_RDWR | O_SYNC);

    uint32_t *gpio_flt_ctrl     = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd_gpio, ADDR_Float_Point_CTRL);
    uint32_t *gpio_flt_data     = gpio_flt_ctrl + 2;

    uint32_t *gpio_in           = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd_gpio, ADDR_GPIO_IN);
    uint32_t *gpio_pl_ps        = gpio_in + 2;

    uint32_t *gpio_out          = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd_gpio, ADDR_GPIO_OUT);
    uint32_t *gpio_out2         = gpio_out + 2;

    uint32_t *gpio_spi_ps_ctrl  = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd_gpio, ADDR_GPIO_SPI_PS_CTRL);
    uint32_t *gpio_spi_ps_data  = gpio_spi_ps_ctrl + 2;

    SCAM_Config.gpio_flt_ctrl   = gpio_flt_ctrl;
    SCAM_Config.gpio_flt_data   = gpio_flt_data;
    SCAM_Config.gpio_in         = gpio_in;
    SCAM_Config.gpio_pl_ps      = gpio_pl_ps;
    SCAM_Config.gpio_out        = gpio_out;
    SCAM_Config.gpio_out2       = gpio_out2;
    SCAM_Config.gpio_spi_ps_ctrl= gpio_spi_ps_ctrl;
    SCAM_Config.gpio_spi_ps_data= gpio_spi_ps_data;

    scfg = &SCAM_Config;

    //////////////////////////////////////////////////////////
    // Pining
    printf(">>>> pinning starts ...\n");
    socket_pinning( gpio_out, 1 );

    // sleep(2);
    uint32_t t_cnt = 1500*1000;
    usleep(t_cnt);

    socket_pinning( gpio_out, 0 );
    printf(">>>> pinning ends ...\n");
    //////////////////////////////////////////////////////////

    gettimeofday(&start, NULL);
    
    gettimeofday(&end, NULL);

    printf("> start fast refresh\n");
    gettimeofday(&start, NULL);
    // set vtrans parameters to temporary values
    scfg->config_ccd_drive->vtrans_num           = 4700;
    scfg->config_ccd_drive->imgCLK1_cnt_min      = 900;
    scfg->config_ccd_drive->imgCLK1_cnt_max      = 2100;
    scfg->config_ccd_drive->imgCLK2_cnt_min      = 300;
    scfg->config_ccd_drive->imgCLK2_cnt_max      = 1500;
    scfg->config_ccd_drive->imgCLK3_cnt_min      = 900;
    scfg->config_ccd_drive->imgCLK3_cnt_max      = 2100;
    scfg->config_ccd_drive->imgCLK4_cnt_min      = 300;
    scfg->config_ccd_drive->imgCLK4_cnt_max      = 1500;
    scfg->config_ccd_drive->imgCLKx_cnt_MAX      = 4000;
    scfg->config_ccd_drive->vtrans_state_cnt_max = 80;
    
    // set htrans parameters to temporary values
    scfg->config_ccd_drive->htrans_num = 1;

    // set htrans_num to 1
    socket_config_ccd_drive(scfg, 
                            scfg->gpio_flt_ctrl, 
                            scfg->gpio_flt_data,
                            scfg->gpio_in,
                            scfg->gpio_pl_ps,
                            scfg->gpio_out,
                            scfg->gpio_out2,
                            scfg->gpio_spi_ps_ctrl,
                            scfg->gpio_spi_ps_data );

    gettimeofday(&end, NULL);
    fprintf(stdout, "[CCD_DRIVE] set to fast refresh mode.\n");
    printf("> change drv params time used: %10.6f seconds\n", time_diff(&start,&end));

    gettimeofday(&start, NULL);
    // fast refresh
    ccd_refresh( scfg->gpio_out, 
                 scfg->gpio_in, 
                 scfg->gpio_pl_ps, 
                 scfg->n_row,
                 scfg->n_col,
                 scfg->n_bytes,
                 0,
                 "" );
    gettimeofday(&end, NULL);
    printf("> refresh time used: %10.6f seconds\n", time_diff(&start,&end));

    gettimeofday(&start, NULL);
    // reset vtrans parameters
    scfg->config_ccd_drive->vtrans_num      = vtrans_num_bak;
    scfg->config_ccd_drive->imgCLK1_cnt_min = imgCLK1_cnt_min_bak;
    scfg->config_ccd_drive->imgCLK1_cnt_max = imgCLK1_cnt_max_bak;
    scfg->config_ccd_drive->imgCLK2_cnt_min = imgCLK2_cnt_min_bak;
    scfg->config_ccd_drive->imgCLK2_cnt_max = imgCLK2_cnt_max_bak;
    scfg->config_ccd_drive->imgCLK3_cnt_min = imgCLK3_cnt_min_bak;
    scfg->config_ccd_drive->imgCLK3_cnt_max = imgCLK3_cnt_max_bak;
    scfg->config_ccd_drive->imgCLK4_cnt_min = imgCLK4_cnt_min_bak;
    scfg->config_ccd_drive->imgCLK4_cnt_max = imgCLK4_cnt_max_bak;
    scfg->config_ccd_drive->imgCLKx_cnt_MAX = imgCLKx_cnt_MAX_bak;
    scfg->config_ccd_drive->vtrans_state_cnt_max = vtrans_state_cnt_max_bak;

    // reset htrans_num
    scfg->config_ccd_drive->htrans_num = htrans_num_bak;

    socket_config_ccd_drive(scfg, 
                            scfg->gpio_flt_ctrl, 
                            scfg->gpio_flt_data,
                            scfg->gpio_in,
                            scfg->gpio_pl_ps,
                            scfg->gpio_out,
                            scfg->gpio_out2,
                            scfg->gpio_spi_ps_ctrl,
                            scfg->gpio_spi_ps_data );

    gettimeofday(&end, NULL);
    fprintf(stdout, "[CCD_DRIVE] reset to nomal readout mode.\n");
/*    printf("> reset drv params time used is %10.6f seconds\n", time_diff(&start,&end));*/

    close(fd_gpio);

    return 0;
}
